import json
from typing import List, Dict
import math

def calculate_distance(point1: List[float], point2: List[float]) -> float:
    """
    计算两点之间的距离（米）
    使用Haversine公式计算地理坐标点之间的距离
    
    Args:
        point1: 第一个点的坐标 [经度, 纬度]
        point2: 第二个点的坐标 [经度, 纬度]
    
    Returns:
        float: 两点之间的距离（米）
    """
    # 地球半径（米）
    R = 6371000
    
    # 转换为弧度
    lat1 = math.radians(point1[1])
    lon1 = math.radians(point1[0])
    lat2 = math.radians(point2[1])
    lon2 = math.radians(point2[0])
    
    # Haversine公式
    dlat = lat2 - lat1
    dlon = lon2 - lon1
    
    a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
    
    return R * c

def simplify_points(points: List[List[float]], distance_threshold: float = 100) -> List[List[float]]:
    """
    基于距离的点抽稀函数
    
    Args:
        points: 原始点列表
        distance_threshold: 距离阈值（米），默认100米
    
    Returns:
        List[List[float]]: 抽稀后的点列表
    """
    if len(points) <= 2:
        return points
    
    result = [points[0]]  # 保留第一个点
    current_idx = 0
    
    while current_idx < len(points) - 1:
        # 从当前点开始，寻找第一个距离大于阈值的点
        next_idx = current_idx + 1
        while next_idx < len(points):
            distance = calculate_distance(points[current_idx], points[next_idx])
            if distance > distance_threshold:
                result.append(points[next_idx])
                current_idx = next_idx
                break
            next_idx += 1
            
            # 如果到达最后一个点，结束循环
            if next_idx == len(points):
                current_idx = next_idx
        
        # 如果已经处理到最后，跳出主循环
        if next_idx >= len(points):
            break
    
    # 确保添加最后一个点
    if points[-1] not in result:
        result.append(points[-1])
    
    return result

def simplify_geojson(input_data: Dict, step: int = 2) -> Dict:
    """
    简化GeoJSON中的线条数据
    
    Args:
        input_data: 输入的GeoJSON数据
        step: 采样步长，默认为2（每两个点取一个）
    
    Returns:
        Dict: 简化后的GeoJSON数据
    """
    output_data = input_data.copy()
    
    total_points_before = 0
    total_points_after = 0
    
    if 'features' not in output_data:
        print("错误：输入的GeoJSON数据格式不正确，缺少'features'字段")
        return output_data
        
    print(f"找到 {len(output_data['features'])} 个要素")
    
    for idx, feature in enumerate(output_data['features']):
        if 'geometry' not in feature or 'type' not in feature['geometry']:
            print(f"警告：要素 {idx} 跳过无效的feature数据")
            continue
            
        print(f"处理要素 {idx}，类型为: {feature['geometry']['type']}")
            
        if feature['geometry']['type'] == 'LineString':
            coords = feature['geometry']['coordinates']
            if coords:  # 确保坐标列表不为空
                print(f"要素 {idx} 包含 {len(coords)} 个点")
                total_points_before += len(coords)
                # 简化单条线
                simplified_coords = simplify_points(coords, step)
                feature['geometry']['coordinates'] = simplified_coords
                total_points_after += len(simplified_coords)
            else:
                print(f"警告：要素 {idx} 的坐标列表为空")
            
        elif feature['geometry']['type'] == 'MultiLineString':
            line_count = len(feature['geometry']['coordinates'])
            print(f"要素 {idx} 是MultiLineString，包含 {line_count} 条线")
            for line_idx, coords in enumerate(feature['geometry']['coordinates']):
                if coords:  # 确保每条线的坐标列表不为空
                    print(f"  线 {line_idx} 包含 {len(coords)} 个点")
                    total_points_before += len(coords)
                else:
                    print(f"警告：要素 {idx} 的线 {line_idx} 坐标列表为空")
            # 简化多条线
            simplified_lines = [
                simplify_points(line_coords, step)
                for line_coords in feature['geometry']['coordinates']
                if line_coords  # 只处理非空的线条
            ]
            feature['geometry']['coordinates'] = simplified_lines
            total_points_after += sum(len(line) for line in simplified_lines)
        else:
            print(f"警告：要素 {idx} 的类型 {feature['geometry']['type']} 不是LineString或MultiLineString")
    
    if total_points_before == 0:
        print("警告：未找到任何有效的点数据")
        return output_data
        
    print(f"\n统计信息:")
    print(f"抽稀前总点数: {total_points_before}")
    print(f"抽稀后总点数: {total_points_after}")
    print(f"减少点数: {total_points_before - total_points_after}")
    print(f"压缩比例: {(1 - total_points_after/total_points_before)*100:.2f}%")
    
    return output_data

def main():
    # 输入输出文件路径
    input_file = "D:/xunJi/python/my/tools/geojson/L2_line2.json"
    output_file = "D:/xunJi/python/my/tools/geojson/L2_line3.json"
    
    # 设置距离阈值（米）
    distance_threshold = 100
    
    try:
        # 读取输入文件
        print(f"\n开始读取文件: {input_file}")
        with open(input_file, 'r', encoding='utf-8') as f:
            input_data = json.load(f)
        
        # 进行数据抽稀
        print("\n开始数据抽稀处理...")
        output_data = simplify_geojson(input_data, distance_threshold)
        
        # 保存结果
        print(f"\n保存结果到文件: {output_file}")
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(output_data, f, ensure_ascii=False, indent=2)
        
        print(f"数据抽稀完成！")
        
    except FileNotFoundError:
        print(f"错误：找不到输入文件 {input_file}")
    except json.JSONDecodeError:
        print(f"错误：输入文件不是有效的JSON格式")
    except Exception as e:
        print(f"处理过程中出现错误: {str(e)}")

if __name__ == "__main__":
    main()